package domain;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletInputStream;

import utils.ByteStack;
import utils.ByteUtils;
import utils.StringUtils;
import utils.StringUtils.MyStringBuffer;

/**
 * use this class to build a new class DownloadableFile
 * @author Evan
 *
 */
public class MultiPart {

//	private Map<String, OnePart> map_parts = new HashMap<String, OnePart>();
	
	private List<OnePart> list_parts = new ArrayList<OnePart>();
	
	/*
	private static final byte[] enter = new byte[]{13,10};
	*/
	
	
	private static byte[] delimiter = null;
	private static byte[] delimiter_end = null;
	
	
	public MultiPart(ServletInputStream sis) throws IOException {
		analyse(sis);
	}


	public MultiPart addOnePart(OnePart op){
//		map_parts.put(op.getName(), op);
		list_parts.add(op);
		return this;
	}

	public OnePart getOnePart(String name){
		OnePart op = null;
		for(OnePart o : list_parts){
			if(o.getName().equals(name)){
				op = o;
				break;
			}
		}
		return op;
	}

	public int getSizeOfPart(){
		return list_parts.size();
	}
	
	public byte[] getData(String name){
		OnePart op = getOnePart(name);
		return op==null?null:op.getData();
	}
	
	public String getValue(String name){
		OnePart op = getOnePart(name);
		return op==null?null:op.getValue();
	}
	
	public List<String> getValueListByName(String name){
		List<String> list_value = new ArrayList<String>();
		for(OnePart op : list_parts){
			if(op.getName().equals(name)){
				list_value.add(op.getValue());
			}
		}
		
		return list_value;
	}
	


	private void analyse(ServletInputStream sis) throws IOException{
		delimiter = null;
		// get delimiter
		ByteStack bs_tmp = new ByteStack();
		int size = -1;
		byte[] b = new byte[4096];
		if(delimiter==null){
			size = sis.readLine(b, 0, b.length);
			// in case of not multi part
			if(size==-1) return;
			bs_tmp.write(b, 0, size);
			delimiter = bs_tmp.getByteArray();
			delimiter_end = ByteUtils.buildByteArray(bs_tmp.getByteArray(0, size-2),'-','-',bs_tmp.getByteArray(size-2, 2));
		}
		readNextOnePart(sis);
	}
	
	private void readNextOnePart(ServletInputStream sis) throws IOException{
		int size = -1;
		byte[] b = new byte[4096];
		OnePart op = new OnePart();
		
		// get header
		for(size = sis.readLine(b, 0, b.length);size>2;size = sis.readLine(b, 0, b.length)){
			op.addHeader(new String(b,0,size));
		}
		
		// get body data
		ByteStack bs_tmp = new ByteStack();
		ByteStack bs_data = new ByteStack();
		for(size = sis.readLine(b, 0, b.length);size!=-1;size = sis.readLine(b, 0, b.length)){
			bs_tmp.reset();
			bs_tmp.write(b, 0, size);
			// if it is delimeter or delimeter_end
			if(size==delimiter.length || size == delimiter_end.length){
				if(ByteUtils.equals(bs_tmp.getByteArray(), delimiter)){
					break;
				}
				if(ByteUtils.equals(bs_tmp.getByteArray(), delimiter_end)){
					break;
				}
			}
			// else add data
			bs_data.write(b, 0, size);
		}
		// check whether comes to the end, if yes, return
		if(bs_data.size()==0) return;
		
		// load data to one part
		op.addData(bs_data.getByteArray(0, bs_data.size()-2));
		addOnePart(op);
		
		
		// read next one part
		readNextOnePart(sis);
	}
	
	
	public String manifest(){
		MyStringBuffer msb = StringUtils.getNewMyStringBuffer();
		for(OnePart op : list_parts){
			msb.println(op.getName());
			msb.println(op.getDataLength());
			if(op.getMime()!=null){
				msb.println(op.getMime());
				msb.println(op.getDataLength());
			}else{
				msb.println(op.getValue());
			}
			msb.println("-----------------------------------");
		}
		
		msb.println("##################################");
		if(delimiter!=null && delimiter_end!=null){
			try {
				msb.println("delimiter: "+delimiter.length+ "  " +new String(delimiter,"utf-8"));
				msb.println("delimiter end: "+delimiter_end.length +"  "+ new String(delimiter_end,"utf-8"));
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}
		
		return msb.getStringAndClose();
	}
	
}
